package mockexample;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.RETURNS_SMART_NULLS;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.*;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class MockitoTutorial {

    @Test
    @DisplayName("验证行为")
    void verifyBehavior() {
        List<Integer> mock = mock(List.class);
        
        mock.add(1);
        mock.clear();
        
        verify(mock).add(1);
    }
    
    @Test
    @DisplayName("模拟期望结果")
    public void when_thenReturn(){
        //mock一个Iterator类
        Iterator<String> iterator = mock(Iterator.class);
        //预设当iterator调用next()时第一次返回hello，第n次都返回world
        when(iterator.next()).thenReturn("hello").thenReturn("world");
        //使用mock的对象
        String result = iterator.next() + " " + iterator.next() + " " + iterator.next();
        //验证结果
        assertEquals("hello world world",result);
    }
    
    @Test
    @DisplayName("模拟抛出异常")
    public void throwException() throws IOException {
        OutputStream outputStream = mock(OutputStream.class);
        
        //预设当流关闭时抛出异常
        doThrow(new IOException()).when(outputStream).close();
        
        assertThatThrownBy(() ->outputStream.close())
        .isInstanceOf(IOException.class);
    }
    
    @Test
    @DisplayName("返回智能空值")
    public void returnsSmartNullsTest() {
        List mock = mock(List.class, RETURNS_SMART_NULLS);
        
        doReturn(23).when(mock).get(0);
        System.out.println(mock.get(0));
        
        //使用RETURNS_SMART_NULLS参数创建的mock对象，不会抛出NullPointerException异常。另外控制台窗口会提示信息“SmartNull returned by unstubbed get() method on mock”
        System.out.println(mock.toArray().length);
    }
}
